package com.example.backend.service;

import com.example.backend.annotation.LogExecution;
import com.example.backend.domain.entity.Ticket;
import com.example.backend.domain.entity.User;
import com.example.backend.domain.enums.TicketStatus;
import com.example.backend.domain.enums.TicketPriority;
import com.example.backend.domain.enums.TicketActionType;
import com.example.backend.dto.TicketFilter;
import com.example.backend.repository.TicketRepository;
import com.example.backend.repository.spec.TicketSpecifications;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.time.Instant;
import java.util.List;
import java.util.Optional;

@Service
@Transactional
public class TicketService {
    private static final Logger log = LoggerFactory.getLogger(TicketService.class);
    
    private final TicketRepository ticketRepository;
    private final TicketHistoryService ticketHistoryService;
    private final DataPermissionService dataPermissionService;
    
    @Autowired(required = false)
    private EmailService emailService;

    public TicketService(TicketRepository ticketRepository, TicketHistoryService ticketHistoryService,
                        DataPermissionService dataPermissionService) {
        this.ticketRepository = ticketRepository;
        this.ticketHistoryService = ticketHistoryService;
        this.dataPermissionService = dataPermissionService;
    }

    @LogExecution("创建工单")
    @CacheEvict(value = {"tickets", "tickets_list", "tickets_stats"}, allEntries = true)
    public Ticket create(Ticket ticket, User creator) {
        String serviceId = "SVC-" + System.currentTimeMillis();
        
        try {
            log.info("╔═══════════════════════════════════════════════════════════════");
            log.info("║ [{}] TicketService.create() 开始", serviceId);
            log.info("╠═══════════════════════════════════════════════════════════════");
            
            // 检查事务状态
            boolean isTransactionActive = TransactionSynchronizationManager.isActualTransactionActive();
            String transactionName = TransactionSynchronizationManager.getCurrentTransactionName();
            boolean isReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
            
            log.info("║ [{}] 事务状态:", serviceId);
            log.info("║   - 事务激活: {}", isTransactionActive);
            log.info("║   - 事务名称: {}", transactionName);
            log.info("║   - 只读模式: {}", isReadOnly);
            log.info("╠═══════════════════════════════════════════════════════════════");
            
            // 记录保存前的实体状态
            log.info("║ [{}] 保存前的工单状态:", serviceId);
            log.info("║   - ID: {} (应为null)", ticket.getId());
            log.info("║   - 标题: {}", ticket.getTitle());
            log.info("║   - 描述: {}", ticket.getDescription());
            log.info("║   - 优先级: {}", ticket.getPriority());
            log.info("║   - 状态: {}", ticket.getStatus());
            log.info("║   - 创建者: {}", creator.getUsername());
            
            // 设置创建者
            ticket.setCreatedBy(creator);
            
            // 如果customer未设置，则默认为创建者
            if (ticket.getCustomer() == null) {
                log.info("║ [{}] Customer 未设置，使用创建者作为客户", serviceId);
                ticket.setCustomer(creator);
            }
            
            // ========== 数据权限优化：确保新建工单对创建者可见 ==========
            // 如果创建者是AGENT且工单未分配，则自动分配给创建者
            if (creator.getRole() == com.example.backend.domain.enums.Role.AGENT 
                && ticket.getAssignedTo() == null) {
                log.info("║ [{}] AGENT创建工单但未分配，自动分配给自己", serviceId);
                ticket.setAssignedTo(creator);
            }
            
            log.info("║ [{}] 准备调用 ticketRepository.save()...", serviceId);
            log.info("╚═══════════════════════════════════════════════════════════════");
            
            // 保存工单
            Ticket savedTicket = ticketRepository.save(ticket);
            
            log.info("╔═══════════════════════════════════════════════════════════════");
            log.info("║ [{}] ✅ ticketRepository.save() 执行完成", serviceId);
            log.info("╠═══════════════════════════════════════════════════════════════");
            log.info("║ [{}] 保存后的工单状态:", serviceId);
            log.info("║   - ID: {} (应有值)", savedTicket.getId());
            log.info("║   - 工单编号: {}", savedTicket.getTicketNumber());
            log.info("║   - 标题: {}", savedTicket.getTitle());
            log.info("║   - 状态: {}", savedTicket.getStatus());
            log.info("║   - 创建时间: {}", savedTicket.getCreatedAt());
            log.info("║   - 更新时间: {}", savedTicket.getUpdatedAt());
            log.info("╚═══════════════════════════════════════════════════════════════");
            
            // 立即验证数据库中是否真的保存了
            log.info("[{}] 🔍 开始数据库验证查询...", serviceId);
            Optional<Ticket> verification = ticketRepository.findById(savedTicket.getId());
            
            if (verification.isPresent()) {
                Ticket verifiedTicket = verification.get();
                log.info("[{}] ✅ 数据库验证成功！工单确实已保存", serviceId);
                log.info("[{}]    验证结果: ID={}, ticketNumber={}, title={}", 
                    serviceId, verifiedTicket.getId(), verifiedTicket.getTicketNumber(), verifiedTicket.getTitle());
                
                // 对比保存结果和查询结果
                if (savedTicket.getId().equals(verifiedTicket.getId()) && 
                    savedTicket.getTicketNumber().equals(verifiedTicket.getTicketNumber())) {
                    log.info("[{}] ✅ 保存结果与查询结果一致", serviceId);
                } else {
                    log.warn("[{}] ⚠️  保存结果与查询结果不一致！", serviceId);
                }
            } else {
                log.error("[{}] ❌ 数据库验证失败！工单ID {} 在数据库中未找到！", serviceId, savedTicket.getId());
                log.error("[{}] ⚠️  这表明可能存在事务问题或数据库操作失败", serviceId);
            }
            
            // 创建历史记录
            log.info("[{}] 创建工单历史记录...", serviceId);
            try {
                ticketHistoryService.createHistory(
                    savedTicket, 
                    creator, 
                    TicketActionType.CREATED, 
                    null, 
                    null, 
                    null, 
                    "工单已创建"
                );
                log.info("[{}] ✅ 历史记录创建成功", serviceId);
            } catch (Exception historyError) {
                log.error("[{}] ❌ 创建历史记录失败（不影响工单创建）: {}", serviceId, historyError.getMessage());
                log.error("[{}] 历史记录错误详情:", serviceId, historyError);
                // 不抛出异常，避免影响主流程
            }
            
            // 发送通知邮件
            if (emailService != null && savedTicket.getAssignedTo() != null) {
                log.info("[{}] 准备发送通知邮件给: {}", serviceId, savedTicket.getAssignedTo().getEmail());
                try {
                    emailService.sendTicketNotification(
                        savedTicket.getAssignedTo().getEmail(),
                        savedTicket.getTicketNumber(),
                        savedTicket.getTitle(),
                        "已分配"
                    );
                    log.info("[{}] ✅ 通知邮件已发送", serviceId);
                } catch (Exception emailError) {
                    log.warn("[{}] ⚠️  发送邮件失败（不影响工单创建）: {}", serviceId, emailError.getMessage());
                }
            } else {
                log.info("[{}] 跳过邮件发送（emailService={}, assignedTo={})", 
                    serviceId, emailService != null, savedTicket.getAssignedTo() != null);
            }
            
            log.info("╔═══════════════════════════════════════════════════════════════");
            log.info("║ [{}] ✅ TicketService.create() 完成", serviceId);
            log.info("║   返回工单: ID={}, ticketNumber={}", savedTicket.getId(), savedTicket.getTicketNumber());
            log.info("╚═══════════════════════════════════════════════════════════════");
            
            return savedTicket;
            
        } catch (Exception e) {
            log.error("╔═══════════════════════════════════════════════════════════════");
            log.error("║ [{}] ❌ TicketService.create() 失败！", serviceId);
            log.error("╠═══════════════════════════════════════════════════════════════");
            log.error("║   - 异常类型: {}", e.getClass().getName());
            log.error("║   - 异常消息: {}", e.getMessage());
            log.error("║   - 工单标题: {}", ticket.getTitle());
            log.error("║   - 创建者: {}", creator.getUsername());
            log.error("╚═══════════════════════════════════════════════════════════════");
            log.error("[{}] 异常堆栈:", serviceId, e);
            
            // 重新抛出异常，触发事务回滚
            throw new RuntimeException("工单创建失败: " + e.getMessage(), e);
        }
    }

    @LogExecution("更新工单")
    @CacheEvict(value = {"tickets", "tickets_list", "tickets_stats"}, allEntries = true)
    public Ticket update(Ticket ticket) {
        return ticketRepository.save(ticket);
    }

    @LogExecution("更新工单状态")
    @CacheEvict(value = "tickets", allEntries = true)
    public Ticket updateStatus(Long ticketId, TicketStatus newStatus, User operator, String note) {
        try {
            log.info("开始更新工单状态: ticketId={}, newStatus={}, operatorId={}", 
                    ticketId, newStatus, operator != null ? operator.getId() : "null");
            
            Ticket ticket = ticketRepository.findById(ticketId)
                    .orElseThrow(() -> new RuntimeException("工单不存在: ID=" + ticketId));
            
            if (operator == null) {
                throw new RuntimeException("操作者不能为空");
            }
            
            TicketStatus oldStatus = ticket.getStatus();
            ticket.setStatus(newStatus);
            
            // 设置解决时间和解决人
            if (newStatus == TicketStatus.RESOLVED && ticket.getResolvedAt() == null) {
                ticket.setResolvedAt(Instant.now());
                ticket.setResolvedBy(operator);
            }
            
            // 设置关闭时间和关闭人
            if (newStatus == TicketStatus.CLOSED && ticket.getClosedAt() == null) {
                ticket.setClosedAt(Instant.now());
                ticket.setClosedBy(operator);
            }
            
            Ticket savedTicket = ticketRepository.save(ticket);
            log.info("工单状态保存成功: ticketId={}, status={}", ticketId, newStatus);
            
            // 创建历史记录（如果失败不影响主流程）
            try {
                String statusNote = note != null && !note.trim().isEmpty() ? 
                        note : "状态已更新为 " + newStatus.name();
                
                ticketHistoryService.createHistory(
                    savedTicket,
                    operator,
                    TicketActionType.STATUS_CHANGED,
                    oldStatus != null ? oldStatus.name() : null,
                    newStatus.name(),
                    "status",
                    statusNote
                );
                log.info("历史记录创建成功");
            } catch (Exception e) {
                log.error("创建历史记录失败，但继续执行: {}", e.getMessage(), e);
                // 历史记录创建失败不影响主流程
            }
            
            log.info("工单状态更新完成: ticketId={}, status={}", ticketId, newStatus);
            return savedTicket;
        } catch (RuntimeException e) {
            log.error("更新工单状态失败: ticketId={}, error={}", ticketId, e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("更新工单状态时发生系统异常: ticketId={}", ticketId, e);
            throw new RuntimeException("更新工单状态失败: " + e.getMessage(), e);
        }
    }

    @LogExecution("分配工单")
    @CacheEvict(value = "tickets", allEntries = true)
    public Ticket assignTicket(Long ticketId, User assignee, User operator) {
        try {
            log.info("开始分配工单: ticketId={}, assigneeId={}, operatorId={}", 
                    ticketId, assignee != null ? assignee.getId() : "null", 
                    operator != null ? operator.getId() : "null");
            
            Ticket ticket = ticketRepository.findById(ticketId)
                    .orElseThrow(() -> new RuntimeException("工单不存在: ID=" + ticketId));
            
            if (assignee == null) {
                throw new RuntimeException("指派人不能为空");
            }
            
            if (operator == null) {
                throw new RuntimeException("操作者不能为空");
            }
            
            User oldAssignee = ticket.getAssignedTo();
            ticket.setAssignedTo(assignee);
            ticket.setStatus(TicketStatus.IN_PROGRESS);
            
            Ticket savedTicket = ticketRepository.save(ticket);
            log.info("工单保存成功: ticketId={}", ticketId);
            
            // 创建历史记录（如果失败不影响主流程）
            try {
                String assigneeName = assignee.getFullName() != null ? assignee.getFullName() : assignee.getUsername();
                String oldAssigneeName = oldAssignee != null && oldAssignee.getFullName() != null ? 
                        oldAssignee.getFullName() : (oldAssignee != null ? oldAssignee.getUsername() : null);
                
                ticketHistoryService.createHistory(
                    savedTicket,
                    operator,
                    TicketActionType.ASSIGNED,
                    oldAssigneeName,
                    assigneeName,
                    "assignedTo",
                    "工单已分配给 " + assigneeName
                );
                log.info("历史记录创建成功");
            } catch (Exception e) {
                log.error("创建历史记录失败，但继续执行: {}", e.getMessage(), e);
                // 历史记录创建失败不影响主流程
            }
            
            // 发送通知邮件（如果失败不影响主流程）
            try {
                if (emailService != null && assignee.getEmail() != null) {
                    emailService.sendTicketNotification(
                        assignee.getEmail(),
                        savedTicket.getTicketNumber(),
                        savedTicket.getTitle(),
                        "已分配"
                    );
                    log.info("通知邮件发送成功");
                }
            } catch (Exception e) {
                log.error("发送通知邮件失败，但继续执行: {}", e.getMessage(), e);
                // 邮件发送失败不影响主流程
            }
            
            log.info("工单分配完成: ticketId={}, assigneeId={}", ticketId, assignee.getId());
            return savedTicket;
        } catch (RuntimeException e) {
            log.error("分配工单失败: ticketId={}, error={}", ticketId, e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("分配工单时发生系统异常: ticketId={}", ticketId, e);
            throw new RuntimeException("分配工单失败: " + e.getMessage(), e);
        }
    }

    @LogExecution("更新工单优先级")
    @CacheEvict(value = "tickets", allEntries = true)
    public Ticket updatePriority(Long ticketId, TicketPriority newPriority, User operator) {
        Ticket ticket = ticketRepository.findById(ticketId)
                .orElseThrow(() -> new RuntimeException("工单不存在"));
        
        TicketPriority oldPriority = ticket.getPriority();
        ticket.setPriority(newPriority);
        
        Ticket savedTicket = ticketRepository.save(ticket);
        
        // 创建历史记录
        ticketHistoryService.createHistory(
            savedTicket,
            operator,
            TicketActionType.PRIORITY_CHANGED,
            oldPriority.name(),
            newPriority.name(),
            "priority",
            "优先级已更新为 " + newPriority.name()
        );
        
        return savedTicket;
    }

    @Transactional(readOnly = true)
    @LogExecution("根据ID查找工单")
    @Cacheable(value = "tickets", key = "#id")
    public Optional<Ticket> findById(Long id) {
        return ticketRepository.findById(id);
    }
    
    /**
     * 根据ID查找工单（带权限验证）
     * @param id 工单ID
     * @param currentUser 当前登录用户
     * @return 工单（如果有权限访问）
     * @throws RuntimeException 如果没有权限访问此工单
     */
    @Transactional(readOnly = true)
    @LogExecution("根据ID查找工单（带权限验证）")
    public Optional<Ticket> findByIdWithPermission(Long id, User currentUser) {
        Optional<Ticket> ticket = ticketRepository.findById(id);
        if (ticket.isPresent()) {
            if (!dataPermissionService.canAccessTicket(ticket.get(), currentUser)) {
                log.warn("用户 {} (角色: {}) 尝试访问无权限的工单 ID: {}", 
                    currentUser.getUsername(), currentUser.getRole(), id);
                throw new RuntimeException("没有权限访问此工单 (ID: " + id + ")");
            }
        }
        return ticket;
    }

    @Transactional(readOnly = true)
    @LogExecution("根据工单编号查找工单")
    @Cacheable(value = "tickets", key = "'number_' + #ticketNumber")
    public Optional<Ticket> findByTicketNumber(String ticketNumber) {
        return ticketRepository.findByTicketNumber(ticketNumber);
    }
    
    /**
     * 根据工单编号查找工单（带权限验证）
     * @param ticketNumber 工单编号
     * @param currentUser 当前登录用户
     * @return 工单（如果有权限访问）
     * @throws RuntimeException 如果没有权限访问此工单
     */
    @Transactional(readOnly = true)
    @LogExecution("根据工单编号查找工单（带权限验证）")
    public Optional<Ticket> findByTicketNumberWithPermission(String ticketNumber, User currentUser) {
        Optional<Ticket> ticket = ticketRepository.findByTicketNumber(ticketNumber);
        if (ticket.isPresent()) {
            if (!dataPermissionService.canAccessTicket(ticket.get(), currentUser)) {
                log.warn("用户 {} (角色: {}) 尝试访问无权限的工单编号: {}", 
                    currentUser.getUsername(), currentUser.getRole(), ticketNumber);
                throw new RuntimeException("没有权限访问此工单 (编号: " + ticketNumber + ")");
            }
        }
        return ticket;
    }

    @Transactional(readOnly = true)
    @LogExecution("获取工单列表")
    @Cacheable(value = "tickets", key = "'list_' + #currentUser.id + '_' + #pageable.pageNumber + '_' + #pageable.pageSize")
    public Page<Ticket> list(Pageable pageable, User currentUser) {
        // 管理员可以访问所有工单，其他角色需要数据权限过滤
        if (currentUser.getRole() == com.example.backend.domain.enums.Role.ADMIN) {
            return ticketRepository.findAll(pageable);
        }
        Specification<Ticket> spec = TicketSpecifications.withDataPermission(currentUser);
        return ticketRepository.findAll(spec, pageable);
    }

    @Transactional(readOnly = true)
    @LogExecution("按条件过滤工单列表")
    @Cacheable(value = "tickets_list", key = "#filter.hashCode() + '_' + #currentUser.id + '_' + #pageable.pageNumber + '_' + #pageable.pageSize")
    public Page<Ticket> list(TicketFilter filter, Pageable pageable, User currentUser) {
        // 组合过滤条件和数据权限
        Specification<Ticket> spec = TicketSpecifications.withFilterAndPermission(filter, currentUser);
        return ticketRepository.findAll(spec, pageable);
    }

    @Transactional(readOnly = true)
    @LogExecution("根据状态获取工单列表")
    @Cacheable(value = "tickets", key = "'status_' + #status + '_' + #currentUser.id + '_' + #pageable.pageNumber + '_' + #pageable.pageSize")
    public Page<Ticket> listByStatus(TicketStatus status, Pageable pageable, User currentUser) {
        // 组合状态过滤和数据权限
        Specification<Ticket> spec = TicketSpecifications.hasStatus(status)
                .and(TicketSpecifications.withDataPermission(currentUser));
        return ticketRepository.findAll(spec, pageable);
    }

    @Transactional(readOnly = true)
    @LogExecution("搜索工单")
    @Cacheable(value = "tickets_search", key = "#keyword + '_' + #status + '_' + #priority + '_' + #assignedToId + '_' + #currentUser.id + '_' + #pageable.pageNumber + '_' + #pageable.pageSize")
    public Page<Ticket> searchTickets(String keyword, TicketStatus status, TicketPriority priority, 
                                     Long assignedToId, Pageable pageable, User currentUser) {
        // 使用Specification实现搜索，以支持数据权限过滤
        Specification<Ticket> spec = TicketSpecifications.hasKeyword(keyword)
                .and(TicketSpecifications.hasStatus(status))
                .and(TicketSpecifications.hasPriority(priority))
                .and(TicketSpecifications.assignedTo(assignedToId))
                .and(TicketSpecifications.withDataPermission(currentUser));
        return ticketRepository.findAll(spec, pageable);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取用户的工单")
    public Page<Ticket> getUserTickets(Long userId, Pageable pageable) {
        return ticketRepository.findByCustomer_Id(userId, pageable);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取分配给用户的工单")
    public Page<Ticket> getAssignedTickets(Long userId, Pageable pageable) {
        return ticketRepository.findByAssignedTo_Id(userId, pageable);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取即将到期的工单")
    public List<Ticket> getUpcomingDueTickets(Instant dueTime, List<TicketStatus> statuses) {
        return ticketRepository.findUpcomingDueTickets(dueTime, statuses);
    }


    @Transactional(readOnly = true)
    @LogExecution("获取工单统计")
    public List<Object[]> getTicketStatsByCustomer(Long customerId) {
        return ticketRepository.getTicketStatsByCustomer(customerId);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取工单统计")
    public List<Object[]> getTicketStatsByAssignee(Long assigneeId) {
        return ticketRepository.getTicketStatsByAssignee(assigneeId);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取工单趋势数据")
    public List<Object[]> getTicketTrendData(Instant startDate, Instant endDate) {
        return ticketRepository.getTicketTrendData(startDate, endDate);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取工单状态分布")
    public List<Object[]> getTicketStatusDistribution() {
        return ticketRepository.getTicketStatusDistribution();
    }

    @Transactional(readOnly = true)
    @LogExecution("获取工单优先级分布")
    public List<Object[]> getTicketPriorityDistribution() {
        return ticketRepository.getTicketPriorityDistribution();
    }

    @Transactional(readOnly = true)
    @LogExecution("获取平均解决时间")
    public Double getAverageResolutionTimeInHours() {
        return ticketRepository.getAverageResolutionTimeInHours();
    }

    @Transactional(readOnly = true)
    @LogExecution("获取SLA达成率")
    @Cacheable(value = "tickets_stats", key = "'sla_' + #slaHours")
    public Double getSlaComplianceRate(Integer slaHours) {
        Long compliantTickets = ticketRepository.getSlaCompliantTickets(slaHours);
        Long totalResolvedTickets = ticketRepository.getTotalResolvedTickets();
        
        if (totalResolvedTickets == 0) {
            return 0.0;
        }
        
        return (double) compliantTickets / totalResolvedTickets * 100;
    }

    // 新增的高级查询方法

    @Transactional(readOnly = true)
    @LogExecution("高级搜索工单")
    @Cacheable(value = "tickets_search", key = "#filter.hashCode() + '_advanced_' + #pageable.pageNumber + '_' + #pageable.pageSize")
    public Page<Ticket> advancedSearch(TicketFilter filter, Pageable pageable) {
        Specification<Ticket> spec = TicketSpecifications.withFilter(filter);
        return ticketRepository.findAll(spec, pageable);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取工单统计信息")
    @Cacheable(value = "tickets_stats", key = "'distribution'")
    public TicketStatistics getTicketStatistics() {
        List<Object[]> statusDistribution = ticketRepository.getTicketStatusDistribution();
        List<Object[]> priorityDistribution = ticketRepository.getTicketPriorityDistribution();
        Double avgResolutionTime = ticketRepository.getAverageResolutionTimeInHours();
        
        return new TicketStatistics(statusDistribution, priorityDistribution, avgResolutionTime);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取用户工单统计")
    @Cacheable(value = "tickets_stats", key = "'user_' + #userId")
    public UserTicketStatistics getUserTicketStatistics(Long userId) {
        List<Object[]> customerStats = ticketRepository.getTicketStatsByCustomer(userId);
        List<Object[]> assigneeStats = ticketRepository.getTicketStatsByAssignee(userId);
        
        return new UserTicketStatistics(customerStats, assigneeStats);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取工单趋势分析")
    @Cacheable(value = "tickets_stats", key = "'trend_' + #startDate + '_' + #endDate")
    public List<Object[]> getTicketTrendAnalysis(Instant startDate, Instant endDate) {
        return ticketRepository.getTicketTrendData(startDate, endDate);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取即将到期工单")
    @Cacheable(value = "tickets", key = "'upcoming_due_' + #dueTime")
    public List<Ticket> getUpcomingDueTickets(Instant dueTime) {
        List<TicketStatus> activeStatuses = List.of(
            TicketStatus.OPEN, 
            TicketStatus.IN_PROGRESS
        );
        return ticketRepository.findUpcomingDueTickets(dueTime, activeStatuses);
    }

    @Transactional(readOnly = true)
    @LogExecution("获取超时工单")
    @Cacheable(value = "tickets", key = "'overdue_' + #cutoffTime + '_' + #status")
    public Page<Ticket> getOverdueTickets(Instant cutoffTime, TicketStatus status, Pageable pageable) {
        return ticketRepository.findOverdueTickets(cutoffTime, status, pageable);
    }

    // 内部统计类
    public static class TicketStatistics {
        private final List<Object[]> statusDistribution;
        private final List<Object[]> priorityDistribution;
        private final Double avgResolutionTime;

        public TicketStatistics(List<Object[]> statusDistribution, List<Object[]> priorityDistribution, Double avgResolutionTime) {
            this.statusDistribution = statusDistribution;
            this.priorityDistribution = priorityDistribution;
            this.avgResolutionTime = avgResolutionTime;
        }

        // Getters
        public List<Object[]> getStatusDistribution() { return statusDistribution; }
        public List<Object[]> getPriorityDistribution() { return priorityDistribution; }
        public Double getAvgResolutionTime() { return avgResolutionTime; }
    }

    public static class UserTicketStatistics {
        private final List<Object[]> customerStats;
        private final List<Object[]> assigneeStats;

        public UserTicketStatistics(List<Object[]> customerStats, List<Object[]> assigneeStats) {
            this.customerStats = customerStats;
            this.assigneeStats = assigneeStats;
        }

        // Getters
        public List<Object[]> getCustomerStats() { return customerStats; }
        public List<Object[]> getAssigneeStats() { return assigneeStats; }
    }
}


